﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Resources;
using EnvDTE;
using Microsoft.Win32;

namespace VsTortoiseSVN.OptionPages
{
    /// <summary>
    /// Represents a page inside the Visual Studio Tools Options dialog.
    /// Unlike in a VsPackage project, for add-ins the page has to be
    /// derived from UserControl rather than DialogPage:
    /// http://social.msdn.microsoft.com/Forums/en/vsx/thread/4a9ae777-1e91-43ed-b69c-6bdd4c2e4151
    /// 
    /// Derive OptionPages from this class!
    /// </summary>
    public class PageBase : UserControl, IDTToolsOptionsPage
    {
        /// <summary>
        /// Constructor
        /// </summary>
        protected PageBase()
        {
        }

        /// <summary>
        /// Sets the specified font to the control and all its sub-controls
        /// </summary>
        private void SetFontRecursive(Control control, Font font)
        {
            control.Font = font;

            foreach (Control ctrl in control.Controls)
            {
                SetFontRecursive(ctrl, font);
            }
        }

        /// <summary>
        /// Sets resource texts to each control where possible
        /// </summary>
        private void SetResourceTextRecursive(Control control)
        {
            // Has the control text a resource string counterpart?
            if (control.Tag != null && control.Tag is string && SatelliteDLL.Instance.HasText(control.Tag as string))
                control.Text = SatelliteDLL.Instance.GetText(control.Tag as string);

            foreach (Control ctrl in control.Controls)
            {
                SetResourceTextRecursive(ctrl);
            }
        }

        /// <summary>
        /// Depending on the current Microsoft Windows visual style/theme, Visual Studio's
        /// Options page has a different size. Unfortunalety, this control has no Parent assigned,
        /// which makes it hard to know what the correct window size would be to fill the entire Options page.
        /// 
        /// Luckily, I found the following method in the http://docproject.codeplex.com project (OptionsDialogBase.cs).
        /// It tries to find the Options window of Visual Studio and reads the size from there.
        /// </summary>
        private void TryResizeToContainer()
        {
            try
            {
                System.Diagnostics.Process vs = System.Diagnostics.Process.GetCurrentProcess();
                IntPtr options = Win32.FindWindowEx(vs.MainWindowHandle, IntPtr.Zero, "#32770", "Options");
                if (options == IntPtr.Zero)
                    // try desktop as parent
                    options = Win32.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "#32770", "Options");
                if (options != IntPtr.Zero)
                {
                    IntPtr container = Win32.FindWindowEx(options, IntPtr.Zero, "#32770", "");
                    if (container != IntPtr.Zero)
                    {
                        Rectangle bounds = Win32.GetWindowRectangle(container);
                        if (bounds.Width > 0 && bounds.Height > 0)
                            this.Size = bounds.Size;
                    }
                }
            }
            catch { }
        } 

        #region IDTToolsOptionsPage Implementation
        public virtual void GetProperties(ref object PropertiesObject)
        {
            PropertiesObject = null;
        }

        public virtual void OnAfterCreated(DTE DTEObject)
        {
            SuspendLayout();

            // If any Control on this page has resource string id as Tag set,
            // this will assign the atual resource string to Text.
            SetResourceTextRecursive(this);

            // This sets the font of all controls to a system default font
            SetFontRecursive(this, SystemFonts.MessageBoxFont);

            // Sets the size of this form to the size of the Visual Studio Options dialog.
            TryResizeToContainer();

            ResumeLayout(true);
        }

        public virtual void OnCancel()
        {
        }

        public virtual void OnHelp()
        {
        }

        public virtual void OnOK()
        {
        }
        #endregion
    }
}
